package io.geekidea.boot.util.baiwangApi;


import com.baiwang.open.client.BWRestClient;
import com.baiwang.open.client.IBWClient;
import com.baiwang.open.client.login.BopLoginClient;
import com.baiwang.open.client.login.BopLoginResponse;
import com.baiwang.open.client.login.PasswordLoginClient;
import com.baiwang.open.client.login.PasswordLoginConfig;
import com.baiwang.open.entity.request.SOutputinvoiceInvoiceRequest;
import com.baiwang.open.entity.request.node.*;
import com.baiwang.open.entity.response.SOutputinvoiceInvoiceResponse;
import com.baiwang.open.exception.BWOpenException;
import io.geekidea.boot.config.baiwang.BaiwangConfig;
import org.springframework.stereotype.Component;


import java.util.*;

/**
 * 开具发票
 */
@Component
public class Invoice {
    static String url = BaiwangConfig.getUrl();
    static String appKey = BaiwangConfig.getAppKey();
    static String userName = BaiwangConfig.getUserName();
    static String password = BaiwangConfig.getPassword();
    static String appSecret = BaiwangConfig.getAppSecret();
    static String userSalt = BaiwangConfig.getUserSalt();

    public static SOutputinvoiceInvoiceResponse issueAnInvoice(
            String orderNo,//开票单号

            String invoiceTerminalCode,//数电账号
            String taxationLabel,//差额征税标签(数电差额票时必填):01-全额开票,02-差额开票

            String invoiceTypeCode,//发票种类编码
            String orderDateTime,//订单日期(yyyy-MM-dd HH:mm:ss)
            String drawer,//开票人
            String payee,//收款人
            String checker,//复核人
            String buyerName,//发票抬头、购方名称

            String pushEmail,//交付邮箱
            String pushPhone,//交付手机

            String taxNo,//销方税号、纳税人识别号
            String sellerAddress,//销方地址
            String sellerPhone,//销方电话
            String sellerBankName,//销方开户行
            String sellerBankNumber,//销方银行账户

            String buyerTaxNo,//购方名称
            String buyerBankNumber,//购方银行账户
            String buyerBankName,//购方开户行
            String buyerTelephone,//购方电话
            String buyerAddress,//购方地址

            String displaySeller,//是否显示销方信息
            String displaySellerAddTel,
            String displayBuyer,
            String displayBuyerAddTel,

            String orderTotalAmount,//发票总金额
//            String goodsTaxRate,//税率
//            String goodsTotalPriceTax,//含税金额
//            String goodsTotalPrice,//不含税金额
//            String goodsTotalTax,//税额

//            String deductibleAmount,//差额扣除额(小数点后2位，传0或者0.00都表示差额征税:0.00，非差额征税传空)

//            String balanceNo,//差额编号
//            String balanceType,//差额凭证类型，凭证类型:01-数电票,02-增值税专用发票,03-增值税普通发票,04-营业税发票,05-财政票据,06-法院裁决书,07-契税完税凭证,08-其他发票类,09-其他扣除凭证
//            String balanceElectricNo,//数电号码:凭证类型为01时必填
//            String balanceInvoiceCode,//发票代码:凭证类型为02、03、04时必填
//            String balanceInvoiceNo,//发票号码:凭证类型为02、03、04时必填
//            String balanceVoucherNo,//凭证号码（如发票号码、完税凭证号等）
//            String balanceIssueDate,// 差额凭证开具日期（格式yyyy-MM-dd）
//            String balanceTotalAmount,//// 差额总金额（小数点后2位）
//            String balanceDeductAmount,// 本次差额扣除金额（小数点后2位，不超过不含税金额）
//            String balanceRemarks ,// 差额备注
//            String balanceSource,// 凭证来源:0-手工录入(默认),1-勾选导入,2-模版导入
//            SOutputinvoiceInvoiceBalanceInfo sOutputinvoiceInvoiceBalanceInfo,
            List<SOutputinvoiceInvoiceBalanceInfo> balanceInfoList,
            List<SOutputinvoiceInvoiceInvoiceDetail> invoiceDetailList,


//            String goodsName,//商品名称
//            String goodsSpecification,//规格型号
//            String goodsUnit,// 单位
//            String goodsQuantity,// 数量
//            String goodsPrice,// 单价
            String priceTaxMark,
            String remarks// 备注
    ) throws BWOpenException {

        // 非必填：纸质发票类型（如04-2016版增值税普通发票(二联折叠票)等）
        String paperInvoiceType = "";
        // 非必填：冲红原因（1-销货退回,2-开票有误,3-服务中止,4-发生销售折让）
        String redInvoiceLabel = "";
        // 非必填：销方地址（长度≤200字符）
//        String sellerAddress = "";
        // 非必填：复核人（长度≤20字符）
//        String checker = "";

        // 旅客运输服务信息列表（数电纸票仅支持1行，特定业务时需填）
        // 必填：出行日期（格式yyyy-MM-dd，仅旅客运输服务信息需填）
        String carriageDate = "";
        // 必填：出行人证件号码（仅旅客运输服务信息需填，长度≤20字符）
        String carriageIdNo = "";
        // 必填：出发地（仅旅客运输服务信息需填，建议省市+详细地址，长度≤80字符）
        String carriageLeave = "";
        // 必填：出行人（仅旅客运输服务信息需填，长度≤20字符）
        String carriageName = "";
        // 必填：交通工具类型（仅旅客运输服务信息需填，1-飞机,2-火车等）
        String carriageVehicleType = "";
        // 必填：出行人证件类型（仅旅客运输服务信息需填，如201-居民身份证）
        String carriageId = "";
        // 必填：到达地（仅旅客运输服务信息需填，建议省市+详细地址，长度≤80字符）
        String carriageArrive = "";
        // 必填：交通工具等级（仅飞机/火车/船舶需填，如飞机-经济舱）
        String carriageVehicleGrade = "";

        // 二手车信息（发票种类编码为04/88时必填）
        // 非必填：卖方国籍(地区)（156-中国,158-中国台湾等）
        String sellerNationalityRegion = "";
        // 非必填：卖方证件号码（卖方为自然人时需填，长度≤20字符）
        String sellerCredentialsNo = "";
        // 必填：卖方电话（仅二手车信息需填，长度≤20字符）
//        String sellerPhone = "";
        // 必填：卖方单位/个人名称（仅二手车信息需填，长度≤80字符）
        String sellerName = "";
        // 必填：厂牌型号（仅二手车信息需填，长度≤60字符）
        String brandModel = "";
        // 必填：卖方地址（仅二手车信息需填，长度≤80字符）
        String sellerAddress2 = "";
        // 非必填：卖方自然人标志（0-否,1-是，默认0）
        String sellerNaturalMark = "";
        // 必填：登记证号（仅二手车信息需填，长度≤20字符）
        String registryNo = "";
        // 非必填：卖方证件类型（卖方为自然人时需填，如201-居民身份证）
        String sellerCredentialsType = "";
        // 必填：车辆识别代码/车架号码（仅二手车信息需填，长度≤23字符）
        String vehicleNo = "";
        // 非必填：反向开具标志（0-正常开具,1-反向开具）
        String reverseIssueMark = "";
        // 必填：卖方税号/身份证号（仅二手车信息需填，长度≤22字符）
        String sellerTaxNo = "";
        // 必填：车牌照号（仅二手车信息需填，长度≤20字符）
        String licensePlate = "";
        // 必填：开票方类型（仅二手车信息需填，1-经销企业,2-拍卖单位,3-市场）
        String organizeType = "";
        // 必填：转入地车辆管理所名称（仅二手车信息需填，长度≤80字符）
        String vehicleAdministration = "";
        // 必填：车辆类型（仅二手车信息需填，长度≤40字符）
        String vehicleType = "";

        // 非必填：抄送邮箱（长度≤50字符）
        String carbonCopyEmail = "";
        // 非必填：红字信息表/确认单编号（冲红时必填，长度≤64字符）
        String redInfoNo = "";
        // 非必填：收款人（长度≤20字符）
//        String payee = "";
        // 非必填：购方证件类型（如201-居民身份证,208-外国护照等）
        String buyerCredentialsType = "";
        // 非必填：购方地址（长度≤200字符）
//        String buyerAddress = "";

        // 不动产经营租赁服务信息列表（特定业务标志为06时必填）
        // 必填：租赁期止（仅租赁信息需填，格式yyyy-MM-dd）
        String leaseHoldDateEnd = "";
        // 非必填：车牌号（仅车辆停放服务需填，长度≤20字符）
        String leaseLicensePlateNo = "";
        // 必填：详细地址（仅租赁信息需填，含关键字如街/路，长度≤120字符）
        String leaseDetailAddress = "";
        // 必填：面积单位（仅租赁信息需填，1-平方千米,2-平方米等）
        String leaseAreaUnit = "";
        // 必填：跨地(市)标志（仅租赁信息需填，0-否,1-是）
        String leaseCrossSign = "";
        // 必填：租赁期起（仅租赁信息需填，格式yyyy-MM-dd）
        String leaseHoldDateStart = "";
        // 必填：不动产地址（仅租赁信息需填，省市县三级，长度≤25字符）
        String leaseAddress = "";
        // 非必填：房屋产权证号（无则自动填“无”，长度≤40字符）
        String leasePropertyNo = "";

        // 非必填：差额征税标签（数电差额票时必填，01-全额开票,02-差额开票）
//        String taxationLabel = "";
        // 非必填：报废产品收购地区（报废业务需填，省市县区四级&分隔，长度≤100字符）
        String scrapProductAddr = "";
        // 非必填：开票终端/数电账号（长度≤30字符）
//        String invoiceTerminalCode = "";
        // 必填：开票类型（1-蓝票,2-红票）
        String invoiceType = "1";
        // 非必填：备注栏是否展示购方地址电话（0-不展示,1-展示）
//        String displayBuyerAddTel = "";
        // 非必填：交付邮箱（用于接收发票，长度≤50字符）
//        String pushEmail = "18230059805@163.com";
        // 非必填：扩展字段（Map格式，key为扩展别名，value为扩展值）
        Map<String, Object> ext = new HashMap<String, Object>();
        // 非必填：交付手机
//        String pushPhone = "18230059805";
        // 必填：开票单号（唯一标识开票订单，长度≤64字符）
//        String orderNo = InvoiceOrderNoGenerator.generateOrderNo()+"B";

        // 非必填：购方税号（企业购方必填，长度≤20字符）
//        String buyerTaxNo = "111111";
        // 非必填：1%转3%放弃优惠理由（特定业务24时用，2-红票/重开,3-放弃优惠）
        String taxReason = "";
        // 非必填：销方电话（长度≤20字符）
        String sellerPhone2 = "";
        // 非必填：原蓝票发票号码（冲红时必填，长度≤8字符）
        String originalInvoiceNo = "";
        // 非必填：原蓝票发票代码（冲红时必填，长度≤12字符）
        String originalInvoiceCode = "";
        // 非必填：清单标志（0-非清单,1-清单，默认0）
        String invoiceListMark = "";
        // 非必填：购方自然人标志（0-否,1-是，仅电子普票自然人归集需填1）
        String naturalMark = "";
        // 非必填：备注栏是否展示销方银行信息（0-不展示,1-展示）
//        String displaySeller = "";
        // 非必填：购方证件号码（购方为自然人时需填，长度≤20字符）
        String buyerCredentialsNo = "";
        // 非必填：销方开户行（长度≤80字符）
//        String sellerBankName = "";
        // 非必填：备注栏是否展示购方银行信息（0-不展示,1-展示）
//        String displayBuyer = "";
        // 非必填：报废产品销售类型（01-自用报废,02-收购报废）
        String scrapSalesType = "";
        // 非必填：共同购买方标志（0-否,1-是，默认0）
        String mulPurchaserMark = "0";
        // 非必填：购方固定电话（长度≤50字符）
//        String buyerTelephone = "";
        // 非必填：抄送手机（长度≤20字符）
        String carbonCopyPhone = "";
        // 必填：单价含税标志（0-不含税,1-含税）
//        String priceTaxMark = "0";

        // 开票明细列表（无明细时可空，最多100行）
        // 非必填：明细扣除额（差额征税填0.00，非差额空，小数点后2位）
//        String deductibleAmount = "";
        // 必填：明细税率（如0.03表示3%，长度≤10字符）
//        String goodsTaxRate = "0.03";
        // 非必填：发票行性质（0-正常行,1-折扣行,2-被折扣行，默认0）
        String invoiceLineNature = "0";
        // 非必填：明细含税金额（未传则按单价*数量计算，长度≤16字符）
//        String goodsTotalPriceTax = "";
        // 非必填：明细不含税金额（未传则按单价*数量计算，长度≤16字符）
//        String goodsTotalPrice = "";
        // 非必填：商品编码（企业自定义编码，长度≤21字符）
        String goodsPersonalCode = "";
        // 非必填：规格型号（长度≤40字符）
//        String goodsSpecification = "";
        // 非必填：明细单价（不含税金额/税额/含税金额全空时必填，保留8位小数，长度≤16字符）
//        String goodsPrice = "119.11";
        // 非必填：零税率标识（空-非零税,1-免税,2-不征税,3-普通零税率）
        String freeTaxMark = "";
        // 非必填：明细数量（不含税金额/税额/含税金额全空时必填，保留8位小数，长度≤16字符）
//        String goodsQuantity = "1";
        // 非必填：明细税额（未传则按单价*数量*税率计算，长度≤16字符）
//        String goodsTotalTax = "";
        // 非必填：单位（如“个”“件”，长度≤20字符）
//        String goodsUnit = "";
        // 非必填：税收分类编码（不传入则自动匹配，长度≤19字符）
        String goodsCode = "";
        // 非必填：优惠政策标识（0-不使用,1-使用，默认0）
        String preferentialMark = "";
        // 必填：商品名称（折扣行需与被折扣行一致，不含编码简称，长度≤90字符）
//        String goodsName = "";
        // 非必填：优惠政策名称（preferentialMark=1时必填，如“简易征收”）
        String vatSpecialManagement = "";

        // 创建煤炭明细特殊信息对象（煤炭类发票明细的补充信息）
        // 非必填：煤炭类型（如1-焦煤,2-动力煤等，参考接口枚举值）
        String coalType = "";

        // 非必填：备注栏是否展示销方地址电话（0-不展示,1-展示，默认0）
//        String displaySellerAddTel = "";
        // 非必填：购方国籍(地区)（如156-中国,158-中国台湾等，参考代码表）
        String buyerNationalityRegion = "";
        // 非必填：机构ID（多机构场景下指定开票机构，单机构可空）
        String orgId = "";

        // 共同购买方列表（当共同购买方标志为1时必填）
        // 非必填：共同购买方名称（长度≤80字符）
        String purchaser = "";
        // 非必填：共同购买方证件号码（根据证件类型填写）
        String certificateNo = "";
        // 非必填：共同购买方证件类型（如201-居民身份证）
        String certificateType = "";

        // 非必填：开票人ID（平台内开票人账号唯一标识）
        String drawerId = "11111111111";

        // 差额征税信息列表（差额征税场景必填）
        // 非必填：差额扣除凭证编号（如发票号码、完税凭证号等）
//        String balanceVoucherNo = "";
        // 非必填：差额扣除类型（1-发票,2-完税凭证等，参考枚举）
//        String balanceType = "";
        // 非必填：差额扣除金额（小数点后2位，不超过不含税金额）
//        String balanceDeductAmount = "";
        // 非必填：差额编号（系统内部标识）
//        String balanceNo = "";
        // 非必填：差额凭证开具日期（格式yyyy-MM-dd）
//        String balanceIssueDate = "";
        // 非必填：差额发票号码（扣除类型为发票时填写）
//        String balanceInvoiceNo = "";
        // 非必填：差额总金额（小数点后2位）
//        String balanceTotalAmount = "";
        // 非必填：差额来源（1-本平台,2-外部，默认1）
//        String balanceSource = "0";
        // 非必填：差额电子凭证号码
//        String balanceElectricNo = "";
        // 非必填：差额发票代码（扣除类型为发票时填写）
//        String balanceInvoiceCode = "";
        // 非必填：差额备注（长度≤200字符）
//        String balanceRemarks = "";

        // 非必填：订单总金额（与发票金额一致，小数点后2位）
//        String orderTotalAmount = "119.11";
        // 非必填：购方开户行（长度≤80字符）
//        String buyerBankName = "";
        // 必填：销方税号（开票企业的纳税人识别号）
//        String taxNo = "338888888888SMB";

        // 二手车特殊信息（二手车发票专用字段）
        // 非必填：二手车电子发票号码
        String usedCarDigitInvoiceNo = "";
        // 非必填：二手车发票代码
        String usedCarInvoiceCode = "";
        // 非必填：二手车发票号码
        String usedCarInvoiceNo = "";

        // 非必填：业务订单号（外部业务系统订单标识，长度≤64字符）
        String bizOrderNo = "";
        // 必填：订单日期时间（格式yyyy-MM-dd HH:mm:ss）
//        String orderDateTime = "2025-09-08 14:04:00";

        // 不动产信息列表（不动产相关业务必填）
        // 非必填：不动产地税编号
        String propertyLandTaxNo = "";
        // 非必填：不动产合同编号
        String propertyContractNo = "";
        // 非必填：不动产成交价格（小数点后2位）
        String propertyDealPrice = "";
        // 非必填：不动产所在地地址（省市县三级）
        String propertyLocalAddress = "";
        // 非必填：不动产跨地标志（0-否,1-是）
        String propertyCrossSign = "";
        // 非必填：不动产面积单位（1-平方米等）
        String propertyAreaUnit = "";
        // 非必填：不动产核定价格（小数点后2位）
        String propertyApprovedPrice = "";
        // 非必填：不动产详细地址（含街路门牌号）
        String propertyDetailAddress = "";
        // 非必填：不动产权证号
        String propertyPropertyNo = "";

        // 非必填：回调地址（接口调用结果通知地址）
        String callBackUrl = "";

        // 煤炭整体信息（煤炭类发票专用字段）
        // 非必填：煤炭发热量（如5500大卡，保留2位小数）
        String coalCalorificValue = "";
        // 非必填：干燥基全硫（煤炭质量指标，保留4位小数）
        String totalSulfurOnDryBasis = "";
        // 非必填：干燥无灰基挥发分（煤炭质量指标，保留2位小数）
        String dryAshFreeVolatileMatter = "";

        // 车辆信息（车辆相关业务必填）
        // 非必填：发动机号码
        String engineNo = "";
        // 非必填：车辆识别代码
        String vehicleNo2 = "";
        // 非必填：产地（如中国上海）
        String originPlace = "";
        // 非必填：核定载客人数
        String passengersLimited = "";
        // 非必填：厂牌型号
        String brandModel2 = "";
        // 非必填：吨位
        String tonnage = "";
        // 非必填：进口凭证号
        String importCertificateNo = "";
        // 非必填：其他凭证号
        String otherCertificateNo = "";
        // 非必填：合格证号
        String certificateNo2 = "";
        // 非必填：检验单号
        String inspectionListNo = "";
        // 非必填：车辆类型
        String vehicleType2 = "";
        // 非必填：缴款凭证号
        String paymentVoucherNo = "";

        // 不动产楼宇信息（不动产楼宇相关业务必填）
        // 非必填：楼宇跨地标志（0-否,1-是）
        String buildingCrossSign = "";
        // 非必填：楼宇详细地址（含街路门牌号）
        String buildingDetailAddress = "";
        // 非必填：楼宇名称
        String buildingName = "";
        // 非必填：跨区管理编号
        String buildingCrossManageNo = "";
        // 非必填：楼宇所在地地址（省市县三级）
        String buildingLocalAddress = "";
        // 非必填：楼宇地税编号
        String buildingLandTaxNo = "";

        // 非必填：业务合同编号（与购方签订的合同编号，长度≤64字符）
        String bizContractNo = "";
        // 非必填：销方银行账号（长度≤30字符）
//        String sellerBankNumber = "987654321";
        // 非必填：购方银行账号（长度≤30字符）
//        String buyerBankNumber = "123456789";

        // 运输信息列表（运输相关业务必填）
        // 非必填：到达地（建议省市+详细地址）
        String transportArrive = "";
        // 非必填：运输工具类型（1-火车,2-汽车等）
        String transportToolType = "";
        // 非必填：运输工具编号（如车牌号、船号等）
        String transportToolNum = "";
        // 非必填：出发地（建议省市+详细地址）
        String transportDeparture = "";
        // 非必填：运输货物名称
        String transportGoodsName = "";

        // 非必填：原电子发票号码（红冲电子发票时必填）
        String originalDigitInvoiceNo = "";
        // 非必填：备注（长度≤230字符）
//        String remarks = "京城保安发票备注";
        // 必填：开票人（长度≤20字符）
//        String drawer = "云冰";
        // 非必填：发票特殊标志（00-正常发票，其他值参考接口枚举）
        String invoiceSpecialMark = "";
        // 非必填：购方名称（长度≤80字符）
//        String buyerName = "京城保安";
        // 非必填：发票种类编码（01-增值税专用发票,02-增值税普通发票等）
//        String invoiceTypeCode = "01";
        String requestId = UUID.randomUUID().toString(); // 非必填：自定义请求唯一标识（默认UUID，用于追踪请求）
        PasswordLoginConfig loginConfig = new PasswordLoginConfig();
        loginConfig.setUrl(url); // 必填：登录请求地址（与开放平台环境地址一致）
        loginConfig.setClientId(appKey); // 必填：客户端ID（即appKey，开发者专属标识）
        loginConfig.setClientSecret(appSecret); // 必填：客户端密钥（即appSecret，用于登录签名）
        loginConfig.setUsername(userName); // 必填：登录用户名
        loginConfig.setPassword(password); // 必填：登录密码
        loginConfig.setUserSalt(userSalt); // 非必填：用户盐值（用户身份验证补充字段）
        BopLoginClient loginClient = new PasswordLoginClient(loginConfig);

        // 获取token, token相关说明请参考 文档中心 -> 用户授权说明
        BopLoginResponse loginResponse = loginClient.login();
        // 重载方法，可以传自定义请求唯一标识
        // BopLoginResponse loginResponse = loginClient.login(requestId);
        String token = loginResponse.getResponse().getAccessToken(); // 必填：从登录响应中获取token（接口调用凭证）


        SOutputinvoiceInvoiceRequest request = new SOutputinvoiceInvoiceRequest();
        request.setPaperInvoiceType(paperInvoiceType); // 非必填：纸质发票类型
        request.setRedInvoiceLabel(redInvoiceLabel); // 非必填：冲红原因
        request.setSellerAddress(sellerAddress); // 非必填：销方地址
        request.setChecker(checker); // 非必填：复核人
        // 旅客运输服务信息列表（数电纸票仅支持1行，特定业务时需填）
        List<SOutputinvoiceInvoiceCarriageInfo> carriageInfoList = new ArrayList<SOutputinvoiceInvoiceCarriageInfo>();
        SOutputinvoiceInvoiceCarriageInfo sOutputinvoiceInvoiceCarriageInfo = new SOutputinvoiceInvoiceCarriageInfo();
        sOutputinvoiceInvoiceCarriageInfo.setCarriageDate(carriageDate); // 必填：出行日期
        sOutputinvoiceInvoiceCarriageInfo.setCarriageIdNo(carriageIdNo); // 必填：出行人证件号码
        sOutputinvoiceInvoiceCarriageInfo.setCarriageLeave(carriageLeave); // 必填：出发地
        sOutputinvoiceInvoiceCarriageInfo.setCarriageName(carriageName); // 必填：出行人
        sOutputinvoiceInvoiceCarriageInfo.setCarriageVehicleType(carriageVehicleType); // 必填：交通工具类型
        sOutputinvoiceInvoiceCarriageInfo.setCarriageId(carriageId); // 必填：出行人证件类型
        sOutputinvoiceInvoiceCarriageInfo.setCarriageArrive(carriageArrive); // 必填：到达地
        sOutputinvoiceInvoiceCarriageInfo.setCarriageVehicleGrade(carriageVehicleGrade); // 必填：交通工具等级
        carriageInfoList.add(sOutputinvoiceInvoiceCarriageInfo);
        request.setCarriageInfoList(carriageInfoList); // 非必填：旅客运输服务信息列表
        // 二手车信息（发票种类编码为04/88时必填）
        SOutputinvoiceInvoiceUsedCarInfo usedCarInfo = new SOutputinvoiceInvoiceUsedCarInfo();
        usedCarInfo.setSellerNationalityRegion(sellerNationalityRegion); // 非必填：卖方国籍(地区)
        usedCarInfo.setSellerCredentialsNo(sellerCredentialsNo); // 非必填：卖方证件号码
        usedCarInfo.setSellerPhone(sellerPhone); // 必填：卖方电话
        usedCarInfo.setSellerName(sellerName); // 必填：卖方单位/个人名称
        usedCarInfo.setBrandModel(brandModel); // 必填：厂牌型号
        usedCarInfo.setSellerAddress(sellerAddress2); // 必填：卖方地址
        usedCarInfo.setSellerNaturalMark(sellerNaturalMark); // 非必填：卖方自然人标志
        usedCarInfo.setRegistryNo(registryNo); // 必填：登记证号
        usedCarInfo.setSellerCredentialsType(sellerCredentialsType); // 非必填：卖方证件类型
        usedCarInfo.setVehicleNo(vehicleNo); // 必填：车辆识别代码/车架号码
        usedCarInfo.setReverseIssueMark(reverseIssueMark); // 非必填：反向开具标志
        usedCarInfo.setSellerTaxNo(sellerTaxNo); // 必填：卖方税号/身份证号
        usedCarInfo.setLicensePlate(licensePlate); // 必填：车牌照号
        usedCarInfo.setOrganizeType(organizeType); // 必填：开票方类型
        usedCarInfo.setVehicleAdministration(vehicleAdministration); // 必填：转入地车辆管理所名称
        usedCarInfo.setVehicleType(vehicleType); // 必填：车辆类型
        request.setUsedCarInfo(usedCarInfo); // 非必填：二手车信息
        request.setCarbonCopyEmail(carbonCopyEmail); // 非必填：抄送邮箱
        request.setRedInfoNo(redInfoNo); // 非必填：红字信息表/确认单编号
        request.setPayee(payee); // 非必填：收款人
        request.setBuyerCredentialsType(buyerCredentialsType); // 非必填：购方证件类型
        request.setBuyerAddress(buyerAddress); // 非必填：购方地址
        // 不动产经营租赁服务信息列表（特定业务标志为06时必填）
        List<SOutputinvoiceInvoiceLeaseInfo> leaseInfoList = new ArrayList<SOutputinvoiceInvoiceLeaseInfo>();
        SOutputinvoiceInvoiceLeaseInfo sOutputinvoiceInvoiceLeaseInfo = new SOutputinvoiceInvoiceLeaseInfo();
        sOutputinvoiceInvoiceLeaseInfo.setLeaseHoldDateEnd(leaseHoldDateEnd); // 必填：租赁期止
        sOutputinvoiceInvoiceLeaseInfo.setLeaseLicensePlateNo(leaseLicensePlateNo); // 非必填：车牌号
        sOutputinvoiceInvoiceLeaseInfo.setLeaseDetailAddress(leaseDetailAddress); // 必填：详细地址
        sOutputinvoiceInvoiceLeaseInfo.setLeaseAreaUnit(leaseAreaUnit); // 必填：面积单位
        sOutputinvoiceInvoiceLeaseInfo.setLeaseCrossSign(leaseCrossSign); // 必填：跨地(市)标志
        sOutputinvoiceInvoiceLeaseInfo.setLeaseHoldDateStart(leaseHoldDateStart); // 必填：租赁期起
        sOutputinvoiceInvoiceLeaseInfo.setLeaseAddress(leaseAddress); // 必填：不动产地址
        sOutputinvoiceInvoiceLeaseInfo.setLeasePropertyNo(leasePropertyNo); // 非必填：房屋产权证号
        leaseInfoList.add(sOutputinvoiceInvoiceLeaseInfo);
        request.setLeaseInfoList(leaseInfoList); // 非必填：不动产经营租赁服务信息列表
        request.setTaxationLabel(taxationLabel); // 非必填：差额征税标签
        request.setScrapProductAddr(scrapProductAddr); // 非必填：报废产品收购地区
        request.setInvoiceTerminalCode(invoiceTerminalCode); // 非必填：开票终端/数电账号
        request.setInvoiceType(invoiceType); // 必填：开票类型
        request.setDisplayBuyerAddTel(displayBuyerAddTel); // 非必填：备注栏是否展示购方地址电话
        request.setPushEmail(pushEmail); // 非必填：交付邮箱
        request.setExt(ext); // 非必填：扩展字段
        request.setPushPhone(pushPhone); // 非必填：交付手机
        request.setOrderNo(orderNo); // 必填：开票单号
        request.setBuyerTaxNo(buyerTaxNo); // 非必填：购方税号
        request.setTaxReason(taxReason); // 非必填：1%转3%放弃优惠理由
        request.setSellerPhone(sellerPhone2); // 非必填：销方电话
        request.setOriginalInvoiceNo(originalInvoiceNo); // 非必填：原蓝票发票号码
        request.setOriginalInvoiceCode(originalInvoiceCode); // 非必填：原蓝票发票代码
        request.setInvoiceListMark(invoiceListMark); // 非必填：清单标志
        request.setNaturalMark(naturalMark); // 非必填：购方自然人标志
        request.setDisplaySeller(displaySeller); // 非必填：备注栏是否展示销方银行信息
        request.setBuyerCredentialsNo(buyerCredentialsNo); // 非必填：购方证件号码
        request.setSellerBankName(sellerBankName); // 非必填：销方开户行
        request.setDisplayBuyer(displayBuyer); // 非必填：备注栏是否展示购方银行信息
        request.setScrapSalesType(scrapSalesType); // 非必填：报废产品销售类型
        request.setMulPurchaserMark(mulPurchaserMark); // 非必填：共同购买方标志
        request.setBuyerTelephone(buyerTelephone); // 非必填：购方固定电话
        request.setCarbonCopyPhone(carbonCopyPhone); // 非必填：抄送手机
        request.setPriceTaxMark(priceTaxMark); // 必填：单价含税标志
        // 开票明细列表（无明细时可空，最多100行）
//            List<SOutputinvoiceInvoiceInvoiceDetail> invoiceDetailList = new ArrayList<SOutputinvoiceInvoiceInvoiceDetail>();
//            SOutputinvoiceInvoiceInvoiceDetail sOutputinvoiceInvoiceInvoiceDetail = new SOutputinvoiceInvoiceInvoiceDetail();
//            sOutputinvoiceInvoiceInvoiceDetail.setExt(ext); // 非必填：明细扩展字段
//            sOutputinvoiceInvoiceInvoiceDetail.setDeductibleAmount(deductibleAmount); // 非必填：扣除额
//            sOutputinvoiceInvoiceInvoiceDetail.setGoodsTaxRate(goodsTaxRate); // 必填：税率
//            sOutputinvoiceInvoiceInvoiceDetail.setInvoiceLineNature(invoiceLineNature); // 非必填：发票行性质
//            sOutputinvoiceInvoiceInvoiceDetail.setGoodsTotalPriceTax(goodsTotalPriceTax); // 非必填：含税金额
//            sOutputinvoiceInvoiceInvoiceDetail.setGoodsTotalPrice(goodsTotalPrice); // 非必填：不含税金额
//            sOutputinvoiceInvoiceInvoiceDetail.setGoodsPersonalCode(goodsPersonalCode); // 非必填：商品编码
//            sOutputinvoiceInvoiceInvoiceDetail.setGoodsSpecification(goodsSpecification); // 非必填：规格型号
//            sOutputinvoiceInvoiceInvoiceDetail.setGoodsPrice(goodsPrice); // 非必填：单价
//            sOutputinvoiceInvoiceInvoiceDetail.setFreeTaxMark(freeTaxMark); // 非必填：零税率标识
//            sOutputinvoiceInvoiceInvoiceDetail.setGoodsQuantity(goodsQuantity); // 非必填：数量
//            sOutputinvoiceInvoiceInvoiceDetail.setGoodsTotalTax(goodsTotalTax); // 非必填：税额
//            sOutputinvoiceInvoiceInvoiceDetail.setGoodsUnit(goodsUnit); // 非必填：单位
//            sOutputinvoiceInvoiceInvoiceDetail.setGoodsCode(goodsCode); // 非必填：税收分类编码
//            sOutputinvoiceInvoiceInvoiceDetail.setPreferentialMark(preferentialMark); // 非必填：优惠政策标识
//            sOutputinvoiceInvoiceInvoiceDetail.setGoodsName(goodsName); // 必填：商品名称
//            sOutputinvoiceInvoiceInvoiceDetail.setVatSpecialManagement(vatSpecialManagement); // 非必填：优惠政策名称
        // 创建煤炭明细特殊信息对象（煤炭类发票明细的补充信息）
        SOutputinvoiceInvoiceCoalDetailInfo coalDetailInfo = new SOutputinvoiceInvoiceCoalDetailInfo();
        coalDetailInfo.setCoalType(coalType); // 非必填：煤炭类型
//            sOutputinvoiceInvoiceInvoiceDetail.setCoalDetailInfo(coalDetailInfo); // 将煤炭明细特殊信息关联到发票明细
//            invoiceDetailList.add(sOutputinvoiceInvoiceInvoiceDetail); // 将发票明细添加到明细列表
        request.setInvoiceDetailList(invoiceDetailList); // 设置发票明细列表到请求对象
        request.setDisplaySellerAddTel(displaySellerAddTel); // 非必填：备注栏是否展示销方地址电话
        request.setBuyerNationalityRegion(buyerNationalityRegion); // 非必填：购方国籍(地区)
        request.setOrgId(orgId); // 非必填：机构ID
        // 共同购买方列表（当共同购买方标志为1时必填）
           /* List<SOutputinvoiceInvoiceMulPurchaser> mulPurchaserList = new ArrayList<SOutputinvoiceInvoiceMulPurchaser>();
            SOutputinvoiceInvoiceMulPurchaser sOutputinvoiceInvoiceMulPurchaser = new SOutputinvoiceInvoiceMulPurchaser();
            sOutputinvoiceInvoiceMulPurchaser.setPurchaser(purchaser); // 非必填：共同购买方名称
            sOutputinvoiceInvoiceMulPurchaser.setCertificateNo(certificateNo); // 非必填：共同购买方证件号码
            sOutputinvoiceInvoiceMulPurchaser.setCertificateType(certificateType); // 非必填：共同购买方证件类型
            mulPurchaserList.add(sOutputinvoiceInvoiceMulPurchaser); // 将共同购买方信息添加到列表
            request.setMulPurchaserList(mulPurchaserList); // 设置共同购买方列表到请求对象*/
        request.setDrawerId(drawerId); // 非必填：开票人ID
        // 差额征税信息列表（差额征税场景必填）
//            List<SOutputinvoiceInvoiceBalanceInfo> balanceInfoList = new ArrayList<SOutputinvoiceInvoiceBalanceInfo>();
//            SOutputinvoiceInvoiceBalanceInfo sOutputinvoiceInvoiceBalanceInfo = new SOutputinvoiceInvoiceBalanceInfo();
//            sOutputinvoiceInvoiceBalanceInfo.setBalanceVoucherNo(balanceVoucherNo); // 非必填：差额扣除凭证编号
//            sOutputinvoiceInvoiceBalanceInfo.setBalanceType(balanceType); // 非必填：差额扣除类型
//            sOutputinvoiceInvoiceBalanceInfo.setBalanceDeductAmount(balanceDeductAmount); // 非必填：差额扣除金额
//            sOutputinvoiceInvoiceBalanceInfo.setBalanceNo(balanceNo); // 非必填：差额编号
//            sOutputinvoiceInvoiceBalanceInfo.setBalanceIssueDate(balanceIssueDate); // 非必填：差额凭证开具日期
//            sOutputinvoiceInvoiceBalanceInfo.setBalanceInvoiceNo(balanceInvoiceNo); // 非必填：差额发票号码
//            sOutputinvoiceInvoiceBalanceInfo.setBalanceTotalAmount(balanceTotalAmount); // 非必填：差额总金额
//            sOutputinvoiceInvoiceBalanceInfo.setBalanceSource(balanceSource); // 非必填：差额来源
//            sOutputinvoiceInvoiceBalanceInfo.setBalanceElectricNo(balanceElectricNo); // 非必填：差额电子凭证号码
//            sOutputinvoiceInvoiceBalanceInfo.setBalanceInvoiceCode(balanceInvoiceCode); // 非必填：差额发票代码
//            sOutputinvoiceInvoiceBalanceInfo.setBalanceRemarks(balanceRemarks); // 非必填：差额备注
//            balanceInfoList.add(sOutputinvoiceInvoiceBalanceInfo); // 将差额信息添加到列表
        request.setBalanceInfoList(balanceInfoList); // 设置差额信息列表到请求对象
        request.setOrderTotalAmount(orderTotalAmount); // 非必填：订单总金额
        request.setBuyerBankName(buyerBankName); // 非必填：购方开户行
        request.setTaxNo(taxNo); // 必填：销方税号
        // 二手车特殊信息（二手车发票专用字段）
        SOutputinvoiceInvoiceUsedCarSpecialInfo usedCarSpecialInfo = new SOutputinvoiceInvoiceUsedCarSpecialInfo();
        usedCarSpecialInfo.setUsedCarDigitInvoiceNo(usedCarDigitInvoiceNo); // 非必填：二手车电子发票号码
        usedCarSpecialInfo.setUsedCarInvoiceCode(usedCarInvoiceCode); // 非必填：二手车发票代码
        usedCarSpecialInfo.setUsedCarInvoiceNo(usedCarInvoiceNo); // 非必填：二手车发票号码
        request.setUsedCarSpecialInfo(usedCarSpecialInfo); // 设置二手车特殊信息到请求对象
        request.setBizOrderNo(bizOrderNo); // 非必填：业务订单号
        request.setOrderDateTime(orderDateTime); // 必填：订单日期时间
        // 不动产信息列表（不动产相关业务必填）
        List<SOutputinvoiceInvoicePropertyInfo> propertyInfoList = new ArrayList<SOutputinvoiceInvoicePropertyInfo>();
        SOutputinvoiceInvoicePropertyInfo sOutputinvoiceInvoicePropertyInfo = new SOutputinvoiceInvoicePropertyInfo();
        sOutputinvoiceInvoicePropertyInfo.setPropertyLandTaxNo(propertyLandTaxNo); // 非必填：不动产地税编号
        sOutputinvoiceInvoicePropertyInfo.setPropertyContractNo(propertyContractNo); // 非必填：不动产合同编号
        sOutputinvoiceInvoicePropertyInfo.setPropertyDealPrice(propertyDealPrice); // 非必填：不动产成交价格
        sOutputinvoiceInvoicePropertyInfo.setPropertyLocalAddress(propertyLocalAddress); // 非必填：不动产所在地地址
        sOutputinvoiceInvoicePropertyInfo.setPropertyCrossSign(propertyCrossSign); // 非必填：不动产跨地标志
        sOutputinvoiceInvoicePropertyInfo.setPropertyAreaUnit(propertyAreaUnit); // 非必填：不动产面积单位
        sOutputinvoiceInvoicePropertyInfo.setPropertyApprovedPrice(propertyApprovedPrice); // 非必填：不动产核定价格
        sOutputinvoiceInvoicePropertyInfo.setPropertyDetailAddress(propertyDetailAddress); // 非必填：不动产详细地址
        sOutputinvoiceInvoicePropertyInfo.setPropertyPropertyNo(propertyPropertyNo); // 非必填：不动产权证号
        propertyInfoList.add(sOutputinvoiceInvoicePropertyInfo); // 将不动产信息添加到列表
        request.setPropertyInfoList(propertyInfoList); // 设置不动产信息列表到请求对象
        request.setCallBackUrl(callBackUrl); // 非必填：回调地址
        // 煤炭整体信息（煤炭类发票专用字段）
        SOutputinvoiceInvoiceCoalInfo coalInfo = new SOutputinvoiceInvoiceCoalInfo();
        coalInfo.setCoalCalorificValue(coalCalorificValue); // 非必填：煤炭发热量
        coalInfo.setTotalSulfurOnDryBasis(totalSulfurOnDryBasis); // 非必填：干燥基全硫
        coalInfo.setDryAshFreeVolatileMatter(dryAshFreeVolatileMatter); // 非必填：干燥无灰基挥发分
        request.setCoalInfo(coalInfo); // 设置煤炭整体信息到请求对象
        // 车辆信息（车辆相关业务必填）
        SOutputinvoiceInvoiceVehicleInfo vehicleInfo = new SOutputinvoiceInvoiceVehicleInfo();
        vehicleInfo.setEngineNo(engineNo); // 非必填：发动机号码
        vehicleInfo.setVehicleNo(vehicleNo2); // 非必填：车辆识别代码
        vehicleInfo.setOriginPlace(originPlace); // 非必填：产地
        vehicleInfo.setPassengersLimited(passengersLimited); // 非必填：核定载客人数
        vehicleInfo.setBrandModel(brandModel2); // 非必填：厂牌型号
        vehicleInfo.setTonnage(tonnage); // 非必填：吨位
        vehicleInfo.setImportCertificateNo(importCertificateNo); // 非必填：进口凭证号
        vehicleInfo.setOtherCertificateNo(otherCertificateNo); // 非必填：其他凭证号
        vehicleInfo.setCertificateNo(certificateNo2); // 非必填：合格证号
        vehicleInfo.setInspectionListNo(inspectionListNo); // 非必填：检验单号
        vehicleInfo.setVehicleType(vehicleType2); // 非必填：车辆类型
        vehicleInfo.setPaymentVoucherNo(paymentVoucherNo); // 非必填：缴款凭证号
        request.setVehicleInfo(vehicleInfo); // 设置车辆信息到请求对象
        request.setDrawer(drawer); // 必填：开票人
        request.setInvoiceSpecialMark(invoiceSpecialMark); // 必填：发票特殊标志
        request.setBuyerName(buyerName); // 必填：购方名称
        // 不动产楼宇信息（不动产楼宇相关业务必填）
        SOutputinvoiceInvoiceBuildingInfo buildingInfo = new SOutputinvoiceInvoiceBuildingInfo();
        buildingInfo.setBuildingCrossSign(buildingCrossSign); // 非必填：楼宇跨地标志
        buildingInfo.setBuildingDetailAddress(buildingDetailAddress); // 非必填：楼宇详细地址
        buildingInfo.setBuildingName(buildingName); // 非必填：楼宇名称
        buildingInfo.setBuildingCrossManageNo(buildingCrossManageNo); // 非必填：跨区管理编号
        buildingInfo.setBuildingLocalAddress(buildingLocalAddress); // 非必填：楼宇所在地地址
        buildingInfo.setBuildingLandTaxNo(buildingLandTaxNo); // 非必填：楼宇地税编号
        request.setBuildingInfo(buildingInfo); // 设置不动产楼宇信息到请求对象
        request.setBizContractNo(bizContractNo); // 非必填：业务合同编号
        request.setSellerBankNumber(sellerBankNumber); // 非必填：销方银行账号
        request.setBuyerBankNumber(buyerBankNumber); // 非必填：购方银行账号
        // 运输信息列表（运输相关业务必填）
        List<SOutputinvoiceInvoiceTransportInfo> transportInfoList = new ArrayList<SOutputinvoiceInvoiceTransportInfo>();
        SOutputinvoiceInvoiceTransportInfo sOutputinvoiceInvoiceTransportInfo = new SOutputinvoiceInvoiceTransportInfo();
        sOutputinvoiceInvoiceTransportInfo.setTransportArrive(transportArrive); // 非必填：到达地
        sOutputinvoiceInvoiceTransportInfo.setTransportToolType(transportToolType); // 非必填：运输工具类型
        sOutputinvoiceInvoiceTransportInfo.setTransportToolNum(transportToolNum); // 非必填：运输工具编号
        sOutputinvoiceInvoiceTransportInfo.setTransportDeparture(transportDeparture); // 非必填：出发地
        sOutputinvoiceInvoiceTransportInfo.setTransportGoodsName(transportGoodsName); // 非必填：运输货物名称
        transportInfoList.add(sOutputinvoiceInvoiceTransportInfo); // 将运输信息添加到列表
        request.setTransportInfoList(transportInfoList); // 设置运输信息列表到请求对象
        request.setOriginalDigitInvoiceNo(originalDigitInvoiceNo); // 非必填：原电子发票号码
        request.setInvoiceTypeCode(invoiceTypeCode); // 必填：发票种类编码
        request.setRemarks(remarks); // 非必填：备注

        IBWClient client = new BWRestClient(url, appKey, appSecret); // 初始化客户端对象
        //IBWClient client = new BWRestClient(url, appKey, appSecret, loginClient); // 初始化客户端对象,传入loginConfig可针对token错误重试1次
        SOutputinvoiceInvoiceResponse response = client.sOutputinvoice().invoice(request, token); // 执行开票请求
        // 重载方法，可传入自定义请求唯一标识
        // SOutputinvoiceInvoiceResponse response = client.sOutputinvoice().invoice(request, token, requestId)
        return response;
    }
}